
cd $directory


************************************************
*Set list of margins; becomes points on x axis
************************************************

global MARGLIST = "50 75 100 150 225 330 500 750 1000 1500 2250 3300 5000 7500 10000 15000 22500 33000 50000 75000 100000"

global LIST = "52201  69006 69106 " //M1GerusoEtAl correctedEconomist correctedSilver 

global SDCF = .067 //in points, = SD/TURNOUT*100
global SD = 100000
global TURNOUT = 150000000

//Parameters from empirical SDs:
global SDSEN = 12.3 //in points,
global SDGOV =  10.4 //in points,
global SDOECD = 9.3 //in points,


************************************************
*Storage for Summary Statistics
************************************************

global STEP = .002	//step along horizontal axis for density plot
global STEP = .004	//step along horizontal axis for density plot
global BINSTART= .42 					//rightmost point of lowest bin
global BINEND = 1 - $BINSTART + $STEP 	//rightmost point of last bin

matrix define REC		=J(30, 10, .) 		//table of summary of reversal rates; columns are models, rows are critical margins of votes dropped from winner or gained by loser
matrix define RECDECWIN	=J(30, 10, .) 		//table of summary of reversal rates; condl on D EC WINS
matrix define RECRECWIN	=J(30, 10, .) 		//table of summary of reversal rates; condl on D EC WINS
matrix define RPV		=J(30, 10, .) 		//table of summary of NPV reversal rates;
matrix define HIST		=J(200, 200, .) 	//table for figure: hist

//define bin starts as first row of F
local row=4
forvalues i=$BINSTART($STEP)$BINEND{ //to hold histogram heights
	matrix HIST[`row', 1] = `i'
	local row = `row' + 1
}


//make a table describing hypothetical NPVs
foreach var in CF {
	matrix define NPV_`var'	=J(200, 2, .) 

	local row=4
	forvalues i=.49(.0002).51{ 
		local last = `i'-.0002
		local next = `i'
		matrix NPV_`var'[`row', 1] = `i'- .0002/2	//first column for horizontal axis
		*local zlast = (`last'-.5)/($SD / $TURNOUT)
		*local znext = (`next'-.5)/($SD / $TURNOUT)
		local zlast = (`last'-.5)/(${SD`var'}/100)
		local znext = (`next'-.5)/(${SD`var'}/100)

		//probability of normal N(.5, [sigma = SD/(.5*turnout)]^2) in the range [next,last]
		local den = normal(`znext') - normal(`zlast') 
		di `zlast' "   " `znext' "   "`den'
		matrix NPV_`var'[`row',2] = `den'
		local row = `row' + 1

	}
}

foreach var in SEN GOV OECD{
	matrix define NPV_`var'	=J(250, 2, .) 

	local row=4
	forvalues i=.30(.005).72{ 
		local last = `i'-.005
		local next = `i'
		matrix NPV_`var'[`row', 1] = `i'- .005/2	//first column for horizontal axis
		*local zlast = (`last'-.5)/($SD / $TURNOUT)
		*local znext = (`next'-.5)/($SD / $TURNOUT)
		local zlast = (`last'-.5)/(${SD`var'}/100)
		local znext = (`next'-.5)/(${SD`var'}/100)

		//probability of normal N(.5, [sigma = SD/(.5*turnout)]^2) in the range [next,last]
		local den = normal(`znext') - normal(`zlast') 
		di `zlast' "   " `znext' "   "`den'
		matrix NPV_`var'[`row',2] = `den'
		local row = `row' + 1

	}
}

************************************************
*Outer loop - open datasets
************************************************

global LOOP = 2

foreach file in $LIST{

	use "source_data`c(dirsep)'`file'.dta", clear

************************************************
*stats and vars
************************************************

//count states 
local error=0
local counter=1
while `error' != 111 {
	qui cap d total_ev_`counter'
	local error=_rc
	local counter=`counter'+1
}
global STATECOUNT = `counter'-2 
di "$STATECOUNT"
local state_count = `counter'-2 


	//make vars that summarize each election
	qui egen pvotes = rowtotal(twoPartyVotes_*)
	forvalues i = 1(1)`state_count'{
		qui gen rvotes_`i' = twoPartyVotes_`i'* R_pvShare_`i'
	}
	qui egen rvotes = rowtotal(rvotes_*)
	qui gen pvshare = rvotes/pvotes
	qui gen margin_share = abs(0.5-pvshare)*2
	qui gen margin_votes = margin_share*pvotes

	forvalues i = 1(1)`state_count'{
		qui gen rwin_`i' = R_pvShare_`i' > .5
		qui gen rev_`i' = rwin_`i' * total_ev_`i'
	}
	qui egen revn_total= rowtotal(rev_*)
	qui egen ev_denominator = rowtotal(total_ev_*)
	qui gen rwin = revn_total/ev_denominator > 0.5
	qui gen dwin = (ev_denominator-revn_total)/ev_denominator > 0.5
	qui gen cf_revn_total  = revn_total
	qui gen cf_rwin = rwin

	
	//This loop identifies which states can flip election on their own (swing==1) and if so, 
	//how many votes must be dropped to do it(vmargin==X)
	forvalues i = 1(1)`state_count'{
		qui gen vmargin_`i' =  twoPartyVotes_`i'*abs(0.5- R_pvShare_`i')*2 //multiply by 2 to get the number of votes that separate candidates ((1-Rshare)-Rshare) = 1-2rshare
		qui replace cf_revn_total = revn_total //reset each loop
		qui replace cf_rwin = rwin //reset each loop
		qui replace cf_revn_total = cf_revn_total - total_ev_`i' if rwin_`i' == 1 //substract state to ECV count if R won the sim
		qui replace cf_revn_total = cf_revn_total + total_ev_`i' if rwin_`i' == 0 //add state from ECV count if R lost the sim
		qui replace cf_rwin =  cf_revn_total/ev_denominator > 0.5 //did R win in the counterfactual flip of the state?
		qui gen swing_`i' = cf_rwin != rwin //did the outcome of the election change? 
		//^this allows a change from not a tie to a tie or vice versa to count as a change
		qui replace vmargin_`i' = . if swing_`i' == 0 //keep vmargin blank if the state can't flip the election alone
		label var vmargin_`i' "The margin in vote counts in state `i'"
		foreach marg in $MARGLIST{
			qui gen swing`marg'_`i' = swing_`i'==1 & vmargin_`i'<`marg'
			label var swing`marg'_`i' "Binary: is vmargin_`i' less than `marg'"
		}
	}
	
	gen closest_flippable_state=.
	qui egen min_vmargin = rowmin(vmargin_*) 
	label var min_vmargin "minimum votes needed to flip closest state"
	qui gen tipping_state = .
	forvalues i = 1(1)`state_count'{
		qui replace closest_flippable_state = `i' if min_vmargin == vmargin_`i'
	}

	//EC Reversals
	egen swingers = rowtotal(swing_*)
	foreach marg in $MARGLIST{
		qui egen swing`marg' = rowtotal(swing`marg'_*)
		qui replace swing`marg' = 0 if swing`marg' == .
		qui gen notReversed`marg' = swing`marg'==0
		label var notReversed`marg' "EC not reversed by one state dropping `marg' votes"
		qui gen Reversed`marg' = (swing`marg'>0 & swing`marg'<51)
		qui replace Reversed`marg' = 0 if swing`marg' == .
		label var Reversed`marg' "EC reversed by at least one state dropping `marg' votes"
		
	}
	drop swing`marg'_*
	
	//NPV Reversals
	foreach marg in $MARGLIST{
		qui gen PVswing`marg'=0
		qui replace PVswing`marg' = 1 if margin_votes<`marg'
		
	}	

	
	qui replace swingers = 0 if swingers == .
	qui gen ec_margin = min_vmargin
	qui gen pv_margin = margin_votes
	
	qui gen zero = swingers == 0
	label var swingers "number of states that could swing election"
	
	*hist swingers, ///
	*	name(swingers, replace) 

		
	//more state level variables
	forvalues s=1(1)$STATECOUNT{
		//rename whig variables, as needed
		cap rename  W_pvShare_`s'  R_pvShare_`s'
		//state vote counts for Rs
		qui gen r_votes_`s' = R_pvShare_`s'*twoPartyVotes_`s'
		//state evs for Rs
		qui gen r_ev_`s' = total_ev_`s' if R_pvShare_`s'>=0.50
		qui replace r_ev_`s' = 0 if R_pvShare_`s'<0.50
	
	}
	
	//buildup string for row totals
	local votestring = "r_votes_1"
	local evstring = "r_ev_1"
	local totalvotesstring = "twoPartyVotes_1"
	local totalevstring = "total_ev_1"
	forvalues s=2(1)$STATECOUNT{ 
		local votestring = "`votestring' r_votes_`s'" 	// R votes row total string
		local evstring = "`evstring' r_ev_`s'"			// R ev row total string
		local totalvotesstring = "`totalvotesstring' twoPartyVotes_`s'" //all votes
		local totalevstring = "`totalevstring' total_ev_`s'" //all evs
	}
	
	//sum to national outcomes
	qui egen r_votes_natl = rowtotal(`votestring')
	qui egen r_ev_natl = rowtotal(`evstring')
	qui egen totalvotes_natl = rowtotal(`totalvotesstring')
	qui egen totalev_natl = rowtotal(`totalevstring')
	
	qui gen cutoff = floor(totalev_natl/2) + 1 
	qui gen r_share_natl = r_votes_natl/totalvotes_natl
	qui gen r_ev_win = (r_ev_natl >= cutoff)
	qui gen r_pv_win = (r_votes_natl>=(totalvotes_natl/2))
	qui gen inv = r_ev_win!=r_pv_win 
	label var r_share_natl "R share nationally"
	label var r_ev_win "R ev win nationally"
	label var r_pv_win "R pv win nationally"
	label var inv "inversion"

	************************************************
	*Data for  figures
	************************************************
	local col = $LOOP
	di `col'
	di `file'
	matrix REC[1, `col'] 		= `file'
	matrix RECDECWIN[1, `col'] 	= `file'
	matrix RECRECWIN[1, `col'] 	= `file'
	matrix RPV[1, `col'] 		= `file'

	local row = 2 //place marglist in rows starting at 2
	//stores fraction of sims reversed by indicated margin
	foreach marg in $MARGLIST{

		matrix REC[`row',1] = `marg'
		matrix RECDECWIN[`row',1] = `marg'
		matrix RECRECWIN[`row',1] = `marg'
		matrix RPV[`row',1] = `marg'
		
		qui summ Reversed`marg'
		matrix REC[`row',`col'] = r(mean)
		qui summ Reversed`marg' if dwin==1
		matrix RECDECWIN[`row',`col'] = r(mean)
		qui summ Reversed`marg' if rwin==1
		matrix RECRECWIN[`row',`col'] = r(mean)
		
		qui summ PVswing`marg'
		matrix RPV[`row',`col'] = r(mean)		
		
		local row = `row'+1
	}
	
	matrix list REC
	
	************************************************
	*Data for density figures
	************************************************
	local col = $LOOP
	
	matrix HIST[1,`col'] 	= `file'

	local row = 4
	forvalues i= $BINSTART($STEP)$BINEND {
		local last = `i'-$STEP
		local next = `i'
		matrix HIST[`row', 1] = `i'- $STEP/2	// first column for horizontal axis
		qui count if r_share_natl>`last' & r_share_natl<=`next' 
		local den = r(N)
		qui count if r_share_natl>`last' & r_share_natl<=`next' & r_ev_win==1 
		local num = r(N)	
		local win = `num'/`den'
		matrix HIST[`row',`col'] = `den'
		local row = `row' + 1
	}

************************************************
*Outer loop - close datasets/convert matrices
************************************************
	
global LOOP = $LOOP +1		
di "$LOOP"
	
}
global ENDLOOP = $LOOP

cap drop REC*
svmat REC
cap drop RPV*
svmat RPV
cap drop HIST*
svmat HIST


*foreach var in HIST2 HIST3 HIST4 HIST5 HIST6 HIST7 { //NPV2{
cap drop NPV*
foreach var in CF SEN GOV OECD{ 
	svmat NPV_`var'
}
foreach var in NPV_CF2{
	qui summ HIST3 in 2/200, d
	local max = r(max)
	qui summ `var' in 2/200, d
	replace `var' = 5*`var'*`max'/r(max)
	
	cap drop ALT`var'
	qui summ NPV_OECD2 in 2/200, d
	local max = r(max)
	qui summ `var' in 2/200, d
	gen ALT`var' = 5*`var'*`max'/r(max)
}


//align the bar heights of histograms, given the 100k v 40k sim runs
replace HIST2=HIST2*4/10

************************************************
*Plot
************************************************

local labsize = "medlarge"
twoway ///
	(connected HIST2 HIST1 in 2/100 , lw(medium) lcolor(black) ms(none) ) ///
	(connected HIST3 HIST1 in 2/100 , lw(medium) lpattern(longdash) lcolor(black) ms(none) ) ///
	(connected HIST4 HIST1 in 2/100 , lw(thin)  lpattern(shortdash) lcolor(black) ms(none) ) ///
	(connected NPV_CF2 NPV_CF1 in 2/100 , lw(thin) lcolor(red) ms(none)) ///
	, ///
	aspect(.5) ///
	ylabel(0 " ", nogrid labsize(medium) axis(1)) ///
	xlabel(.42(.02).58, nogrid labsize(`labsize')) ///
	xline(.5, lcolor(gs11) lpattern(dash) ) ///
	xtitle("Republican Share of NPV", size(`labsize')) ///
	ytitle("Probability", size(medium) axis(1)) ///
	graphr(c(white) lc(white)) ///
	legend(order(2 "Gelman et al., 2020" 1 "Geruso et al., 2022"  3 "Silver, 2020"  4 "Counterfactual NPV with" "vulnerability matched to EC") position(2) col(1) ring(0) region(lwidth(thin)) size(small))  ///
	name(histoverlay_cfModels, replace) 
	
	graph export "figures`c(dirsep)'Figure3a.pdf", replace
	
local labsize = "medlarge"
twoway ///
	(connected NPV_SEN2 NPV_SEN1 in 2/250 , lw(thick) lcolor(gs13) ms(none) ) ///
	(connected NPV_GOV2 NPV_GOV1 in 2/250 , lw(medthick)  lpattern(solid) lcolor(gs6) ms(none) ) ///
	(connected NPV_OECD2 NPV_OECD1 in 2/250 , lw(thin)    lpattern(solid) lcolor(black) ms(none) ) ///
	(connected ALTNPV_CF2 NPV_CF1 in 2/200 , lw(thin) lcolor(red) ms(none)) ///
	, ///
	aspect(.5) ///
	ylabel(0 " ", nogrid labsize(medium) axis(1)) ///
	xlabel(.3(.05).7, nogrid labsize(`labsize')) ///
	xline(.5, lcolor(gs11) lpattern(dash) ) ///
	xtitle("Index Party Share of NPV", size(`labsize')) ///
	ytitle("Probability", size(medium) axis(1)) ///
	graphr(c(white) lc(white)) ///
	legend(order(1 "Senate Average Spread" 2 "Governor Average Spread" 3 "OECD Average Spread" 4 "Counterfactual NPV with" "vulnerability matched to EC") position(2) col(1) ring(0) region(lwidth(thin)) size(small))  ///
	name(histoverlay_cfPops, replace) 
	
	graph export "figures`c(dirsep)'Figure3b.pdf", replace	


	
	
	

	
